<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>观察者模式</title>
</head>
<body>
<style type="text/css">
    body {
        color: #000;
        background: #BF4040;
    }
</style>
<script>
    /**
     //queueObj v1
     var wxInterface = {
        queue: function (func) {
            if (wxInterface.state) {
                func();
            } else {
                var queueCount = 0;
                var queueList = setInterval(function () {
                    queueCount++;
                    if (wxInterface.state) {
                        clearInterval(queueList);
                        func();
                    }
                    if (queueCount > 7) {
                        clearInterval(queueList);
                        console.log('微信分享初始化失败');
                    }
                }, 700);
            }
        },
        wxShareZone: function (data, callback, cancelback, triggercallback) {//微信朋友圈
        },
        wxShareFriend: function (data, callback, cancelback, triggercallback) {//微信朋友
        },
    }

     //queueObj v1.0.0  调用
     wxInterface.queue(function () {
        wxInterface.wxShareZone(data, function (res) {
            //strUtils.sendByShare4StatisticCallback(childrenId['id'], config.shareChannel.wxZone);
        }, undefined, undefined);
        wxInterface.wxShareFriend(data, function (res) {
            //strUtils.sendByShare4StatisticCallback(childrenId['id'], config.shareChannel.wxFriend);
        }, undefined, undefined);
    });

     */
    /**
     //queueObj v2
     var queueObjv2 = {
        queue: function (flag, fncb, fnerr) {
            if (flag) {
                (Object.prototype.toString.call(fncb) === '[object Function]') ? fncb() : null;
            } else {
                var queueCount = 0;
                var queueList = setInterval(function () {
                    console.log('queue：第' + queueCount + '次进行Check');
                    queueCount++;
                    if (flag) {
                        clearInterval(queueList);
                        (Object.prototype.toString.call(fncb) === '[object Function]') ? fncb() : null;
                    }
                    if (queueCount >= 10) {
                        clearInterval(queueList);
                        (Object.prototype.toString.call(fnerr) === '[object Function]') ? fnerr() : null;
                        console.log('执行失败');
                    }
                }, 300);
            }
        },
    }

     var isFlag = false;

     queueObjv2.queue((isFlag), function () {
        console.log('可以执行了！');
    }, function () {
        console.log('最终无法执行');
    });

     setTimeout(function () {
        isFlag = true;
        console.log('状态改变');
    }, 1000);




     /!*
     queue：第0次进行Check
     观察者模式.html:56 queue：第1次进行Check
     观察者模式.html:56 queue：第2次进行Check
     观察者模式.html:82 状态改变
     观察者模式.html:56 queue：第3次进行Check
     观察者模式.html:56 queue：第4次进行Check
     观察者模式.html:56 queue：第5次进行Check
     观察者模式.html:56 queue：第6次进行Check
     观察者模式.html:56 queue：第7次进行Check
     观察者模式.html:56 queue：第8次进行Check
     观察者模式.html:56 queue：第9次进行Check
     观察者模式.html:77 最终无法执行
     观察者模式.html:65 执行失败*!/

     //flag 不可当值来传*/

    /**
     * 观察者模式
     function Observer() {
        this.fns = [];
    }
     Observer.prototype = {
        subscribe: function (fn) {
            this.fns.push(fn);
        },
        unsubscribe: function (fn) {
            this.fns = this.fns.filter(
                    function (el) {
                        if (el !== fn) {
                            return el;
                        }
                    }
            );
        },
        update: function (o, thisObj) {
            var scope = thisObj || window;
            this.fns.forEach(
                    function (el) {
                        el.call(scope, o);
                    }
            );
        }
    };


     //测试
     var o = new Observer;
     var f1 = function (data) {
        console.log('Robbin: ' + data + ', 赶紧干活了！');
    };

     var f2 = function (data) {
        console.log('Randall: ' + data + ', 找他加点工资去！');
    };

     o.subscribe(f1);
     o.subscribe(f2);

     o.update("Tom回来了！")

     //退订f1
     o.unsubscribe(f1);
     //再来验证
     o.update("Tom回来了！");*/

    var queueObj = {
        config: {
            Taskqueue: new Set(),//事件列表
            timeLineHz: 300,//时间轴频率
            timeLineCount: 0//时间轴本次计数总和
        },
        fn: function (parame) {
            let self = this;
            parame.timecount = self.config.timeLineHz;//初始化对象时间计数.初始为IntervalTime为防止时间频率溢出timeout。
            self.config.Taskqueue.add(parame);//将任务增加至队列
            self.timeLine ? (console.log(parame.flagname, '已增加至队列，', '时间轴已存在')) : self.addTimeLine();
        },
        addTimeLine: function () {//启动时间轴
            let self = this;
            console.log('启动时间轴');
            self.timeLine = setInterval(function () {
                self.config.timeLineCount++;
                //console.log('时间轴执行', self.config.timeLineCount, new Date().getSeconds());
                for (let entity of  self.config.Taskqueue) {
                    //console.log('执行任务：', entity.flagname, new Date().getSeconds());
                    entity.timecount = entity.timecount + self.config.timeLineHz;
                    if (entity.flag === self[entity.flagname]) {
                        self.delFlag(entity, {static: 1, msg: '标识确认更新'});
                    } else if (entity.timecount >= entity.timeout) {
                        self.delFlag(entity, {static: 0, msg: '超时未更新标识'});
                    }
                    /**
                     * 多级队列
                     * for (let item of parame.flagList) {
                        //console.log(this.checkFlag(item.flag, this[parame.flagname]));
                        self.checkFlag(item.flag, self[parame.flagname]) ? (cb(parame.flagname + ' 标识确认 ' + item.flag)) : (cb(parame.flagname + ' 标识不确认 ' + item.flag));
                    }*/
                }
                self.config.Taskqueue.size ? undefined : (clearInterval(self.timeLine), self.timeLine = false, console.log('无队列，暂停时间轴'));
                //如果无任务则clear定时器
            }, self.config.timeLineHz);
        },
        delFlag: function (flag, msg) {
            let self = this;
            flag.queueFun(msg);
            self.config.Taskqueue.delete(flag);
        },
    };

    queueObj.qflag = 1;//在其他作用域中设置此变量
    queueObj.qflag2 = 10;//在其他作用域中设置此变量

    //新增第一个任务
    queueObj.fn({
        flagname: 'qflag',
        timeout: 2000,
        flag: 2,
        queueFun: function (msg) {
            console.log(this.flagname, msg);
        }
    });
    //新增第二个任务
    setTimeout(function () {
        queueObj.fn({
            flagname: 'qflag2',
            timeout: 10000,
            flag: 10,
            queueFun: function (msg) {
                console.log(this.flagname, msg);
            }
        });
    }, 1000);


    //启动时间轴
    //观察者模式.html:171 qflag2  已新增到时间轴
    //观察者模式.html:224 qflag2 Object {static: 1, msg: "标识确认更新"}
    //观察者模式.html:214 qflag Object {static: 0, msg: "超时未更新标识"}
    //观察者模式.html:194 无队列，暂停时间轴

</script>
</body>
</body>
</html>